home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************
- Project : MacPerl - Standalone Perl
- File : MPConsole.cp - Console interface for GUSI
- Author : Matthias Neeracher
- Language : MPW C/C++
-
- $Log: MPConsole.cp,v $
- Revision 1.2 1994/05/04 02:49:57 neeri
- Safer Interrupts.
-
- Revision 1.1 1994/02/27 23:04:58 neeri
- Initial revision
-
- Revision 0.2 1993/08/30 00:00:00 neeri
- ShowWindow -> DoShowWindow
-
- Revision 0.1 1993/08/14 00:00:00 neeri
- Remember rectangles
-
- *********************************************************************/
-
- #include <GUSIFile_P.h>
-
- #include <Resources.h>
- #include <Windows.h>
- #include <Errors.h>
- #include <Folders.h>
- #include <PLStringFuncs.h>
- #include <LowMem.h>
- #include <OSEvents.h>
-
- #include <ioctl.h>
- #include <sys/types.h>
- #include <Signal.h>
-
- #include "MPConsole.h"
-
- extern "C" {
- #include "MPGlobals.h"
- #include "MPAppleEvents.h"
- #include "MPWindow.h"
- #include "MPFile.h"
- #include "MPMain.h"
- }
-
- class MPConsoleSocket; // That's what this file's all about
-
- class MPConsoleSocket : public Socket {
- friend class MPConsoleSocketDomain;
- friend void CloseConsole(Ptr cookie);
- friend void HarvestConsole(DPtr doc, MPConsoleSocket * sock);
- friend int MPConsoleSpin(spin_msg msg, long arg);
-
- MPConsoleSocket(DPtr window);
-
- virtual ~MPConsoleSocket();
-
- DPtr window;
- Handle input;
- Boolean nonblocking;
- Boolean eof;
- public:
- virtual int read(void * buffer, int buflen);
- virtual int write(void * buffer, int buflen);
- virtual int fcntl(unsigned int cmd, int arg);
- virtual void pre_select(Boolean wantRead, Boolean wantWrite, Boolean wantExcept);
- virtual int select(Boolean * canRead, Boolean * canWrite, Boolean * exception);
- virtual void post_select(Boolean wantRead, Boolean wantWrite, Boolean wantExcept);
- virtual int ioctl(unsigned int request, void *argp);
- virtual int isatty();
- };
-
- class MPConsoleSocketDomain : public FileSocketDomain {
- MPConsoleSocket * first;
- enum {
- stdInput,
- stdOutput,
- stdError,
- stdConsole,
- userConsole
- } consoleClass;
- public:
- MPConsoleSocketDomain() : FileSocketDomain(AF_UNSPEC, true, false) { }
-
- virtual Boolean Yours(const GUSIFileRef & ref, Request request);
- virtual Socket * open(const GUSIFileRef & ref, int oflag);
- };
-
- MPConsoleSocketDomain MPConsoleSockets;
-
- #if !defined(powerc) && !defined(__powerc)
- #pragma segment MPConsole
- #endif
-
- /************************ MPConsoleSocket members ************************/
-
- void HarvestConsole(DPtr doc, MPConsoleSocket * sock)
- {
- HLock((*doc->theText)->hText);
-
- char * chr = *(*doc->theText)->hText + (*doc->theText)->teLength;
- char * end = *(*doc->theText)->hText + doc->u.cons.fence;
-
- if (gGotEof == doc) {
- PtrAndHand(end, sock->input, chr - end);
-
- doc->u.cons.fence = (*doc->theText)->teLength;
- sock->eof = true;
- } else
- while (chr-- > end)
- if (*chr == '\n') {
- PtrAndHand(end, sock->input, ++chr - end);
- doc->u.cons.fence = chr - *(*doc->theText)->hText;
-
- break;
- }
-
- HUnlock((*doc->theText)->hText);
- }
-
- MPConsoleSocket::MPConsoleSocket(DPtr window)
- : window(window)
- {
- nonblocking = false;
- eof = false;
- input = NewHandle(0);
-
- if (window)
- window->u.cons.cookie = Ptr(this);
- }
-
- void CloseConsole(Ptr cookie)
- {
- if (cookie)
- ((MPConsoleSocket *) cookie)->window = nil;
- }
-
- MPConsoleSocket::~MPConsoleSocket()
- {
- DisposeHandle(input);
-
- if (window) {
- window->u.cons.cookie = nil;
-
- if (!((WindowPeek) window->theWindow)->visible)
- CloseMyWindow(window->theWindow);
- }
- }
-
- int MPConsoleSocket::fcntl(unsigned int cmd, int arg)
- {
- switch (cmd) {
- case F_GETFL:
- if (nonblocking)
- return FNDELAY;
- else
- return 0;
- case F_SETFL:
- if (arg & FNDELAY)
- nonblocking = true;
- else
- nonblocking = false;
-
- return 0;
- default:
- return GUSI_error(EOPNOTSUPP);
- }
- }
-
- int MPConsoleSocket::ioctl(unsigned int request, void *argp)
- {
- switch (request) {
- case FIONBIO:
- nonblocking = (Boolean) *(long *) argp;
-
- return 0;
- case FIONREAD:
- *(unsigned long *) argp = GetHandleSize(input);
-
- return 0;
- case FIOINTERACTIVE:
- return 0;
- case WIOSELECT:
- if (window)
- SelectWindow(window->theWindow);
-
- return 0;
- default:
- return GUSI_error(EOPNOTSUPP);
- }
- }
-
- int MPConsoleSocket::read(void * buffer, int buflen)
- {
- int avail;
-
- avail = int(GetHandleSize(input));
-
- if (!avail) {
- if (eof) {
- eof = false;
-
- return 0;
- }
- if (!window)
- return 0;
- else if (nonblocking)
- return GUSI_error(EWOULDBLOCK);
- else {
- if (!((WindowPeek) window->theWindow)->visible)
- DoShowWindow(window->theWindow);
- if (!((WindowPeek) window->theWindow)->hilited)
- SelectWindow(window->theWindow);
-
- window->u.cons.selected = true;
- ShowWindowStatus();
-
- SPIN(!(avail = int(GetHandleSize(input))) && !eof && window, SP_STREAM_READ, 0);
-
- if (!avail && eof)
- eof = false;
-
- window->u.cons.selected = false;
- ShowWindowStatus();
- }
- }
-
- buflen = min(avail, buflen);
-
- HLock(input);
- memcpy(buffer, *input, buflen);
- if (avail -= buflen)
- memcpy(*input, *input+buflen, avail);
- HUnlock(input);
- SetHandleSize(input, avail);
-
- return buflen;
- }
-
- int MPConsoleSocket::write(void * buffer, int buflen)
- {
- short oldStart;
- short oldEnd;
- int len = buflen;
-
- if (!window)
- return GUSI_error(ESHUTDOWN);
-
- HarvestConsole(window, this);
-
- if (len > window->u.cons.memory) {
- buffer = (void *) (Ptr(buffer) + len - window->u.cons.memory);
- len = window->u.cons.memory;
- }
-
- (*window->theText)->teLength += buflen;
- EnforceMemory(window, window->theText);
- (*window->theText)->teLength -= buflen;
-
- oldStart = (*window->theText)->selStart;
- oldEnd = (*window->theText)->selEnd;
-
- if (oldStart >= window->u.cons.fence)
- oldStart += buflen;
- if (oldEnd >= window->u.cons.fence)
- oldEnd += buflen;
-
- TESetSelect(window->u.cons.fence, window->u.cons.fence, window->theText);
- TEInsert(buffer, buflen, window->theText);
-
- if (!((WindowPeek) window->theWindow)->visible) {
- HideControl(window->vScrollBar);
- HideControl(window->hScrollBar);
-
- DoShowWindow(window->theWindow);
- }
-
- ShowSelect(window);
- DrawPageExtras(window);
-
- TESetSelect(oldStart, oldEnd, window->theText);
-
- if (window->u.cons.fence < 32767)
- window->u.cons.fence += buflen;
-
- return buflen;
- }
-
- static Boolean StatusNeedsUpdate = false;
-
- void MPConsoleSocket::pre_select(Boolean canRead, Boolean, Boolean)
- {
- if (canRead && window) {
- StatusNeedsUpdate = window->u.cons.selected = true;
-
- if (!((WindowPeek) window->theWindow)->visible)
- DoShowWindow(window->theWindow);
- }
- }
-
- void MPConsoleSocket::post_select(Boolean canRead, Boolean, Boolean)
- {
- if (canRead && window)
- StatusNeedsUpdate = window->u.cons.selected = false;
- }
-
- int MPConsoleSocket::select(Boolean * canRead, Boolean * canWrite, Boolean * exception)
- {
- int goodies = 0;
-
- if (StatusNeedsUpdate) {
- ShowWindowStatus();
-
- StatusNeedsUpdate = false;
- }
-
- if (canRead)
- if (*canRead = (GetHandleSize(input) > 0 || eof))
- ++goodies;
-
- if (canWrite) {
- *canWrite = true;
- ++goodies;
- }
-
- if (exception)
- *exception = false;
-
- return goodies;
- }
-
- int MPConsoleSocket::isatty()
- {
- return 1;
- }
-
- /********************* MPConsoleSocketDomain members **********************/
-
- #if !defined(powerc) && !defined(__powerc)
- #pragma force_active on
- #endif
-
- Boolean MPConsoleSocketDomain::Yours(const GUSIFileRef & ref, FileSocketDomain::Request request)
- {
- if (ref.spec || (request != willOpen))
- return false;
-
- switch (ref.name[4] | 0x20) {
- case 's':
- if (gRemoteControl)
- return false;
- if ((ref.name[5] | 0x20) != 't' || (ref.name[6] | 0x20) != 'd')
- return false;
- switch (ref.name[7] | 0x20) {
- case 'i':
- if ((ref.name[8] | 0x20) != 'n' || ref.name[9])
- return false;
- consoleClass = stdInput;
-
- return true;
- case 'o':
- if ((ref.name[8] | 0x20) != 'u' || (ref.name[9] | 0x20) != 't' || ref.name[10])
- return false;
- consoleClass = stdOutput;
-
- return true;
- case 'e':
- if ((ref.name[8] | 0x20) != 'r' || (ref.name[9] | 0x20) != 'r' || ref.name[10])
- return false;
- consoleClass = stdError;
-
- return true;
- default:
- return false;
- }
- case 'c':
- if ( (ref.name[5] | 0x20) != 'o' || (ref.name[6] | 0x20) != 'n'
- || (ref.name[7] | 0x20) != 's' || (ref.name[8] | 0x20) != 'o'
- || (ref.name[9] | 0x20) != 'l' || (ref.name[10] | 0x20) != 'e')
- return false;
- switch (ref.name[11]) {
- case 0:
- consoleClass = stdConsole;
-
- return true;
- case ':':
- consoleClass = userConsole;
-
- return true;
- default:
- return false;
- }
- default:
- return false;
- }
- }
-
- Socket * MPConsoleSocketDomain::open(const GUSIFileRef & ref, int flags)
- {
- DPtr doc;
- Socket * sock = nil;
- char title[256];
- Boolean nudoc = false;
-
- switch (consoleClass) {
- case stdInput:
- flags = O_RDONLY;
-
- break;
- case stdOutput:
- flags = O_WRONLY;
-
- break;
- case stdError:
- flags = O_WRONLY;
-
- break;
- default:
- break;
- }
-
- if (consoleClass == userConsole) {
- for (doc = gConsoleList; doc; doc = doc->u.cons.next)
- if (doc->kind == kConsoleWindow) {
- getwtitle(doc->theWindow, title);
-
- if (equalstring(title, (char *) ref.name+12, false, true)) {
- if (doc->u.cons.cookie)
- sock = (Socket *) doc->u.cons.cookie;
-
- goto found;
- }
- }
-
- nudoc = true;
- doc = NewDocument(false, kConsoleWindow);
-
- setwtitle(doc->theWindow, (char *) ref.name+12);
-
- RestoreConsole(doc);
- } else {
- for (doc = gConsoleList; doc; doc = doc->u.cons.next)
- if (doc->kind == kWorksheetWindow) {
- if (doc->u.cons.cookie)
- sock = (Socket *) doc->u.cons.cookie;
-
- goto found;
- }
-
- nudoc = true;
- doc = NewDocument(false, kWorksheetWindow);
- SetWTitle(doc->theWindow, LMGetCurApName());
-
- RestoreConsole(doc);
- }
-
- found:
- if (!sock) {
- errno = 0;
- sock = new MPConsoleSocket(doc);
-
- if (sock && errno) {
- if (nudoc)
- CloseMyWindow(doc->theWindow);
-
- delete sock;
-
- return nil;
- }
- } else
- ((MPConsoleSocket *)sock)->eof = false;
-
- if (!(flags & 1) && doc)
- doc->u.cons.fence = (*doc->theText)->teLength;
- else if (nudoc)
- doc->u.cons.fence = 32767;
-
- return sock;
- }
-
- /********************* A kinder, gentler, spin **********************/
-
- int MPConsoleSpin(spin_msg spin, long)
- {
- if (!gInBackground && GUSIInterrupt() && gRunningPerl) {
- FlushEvents(-1, 0);
-
- if (spin == SP_AUTO_SPIN)
- longjmp(gExitPerl, -128);
- else
- return -1;
- }
-
- MainEvent(spin != SP_SELECT && spin != SP_STREAM_READ);
-
- for (DPtr doc = gConsoleList; doc; doc = doc->u.cons.next)
- if (doc->dirty) {
- if (doc->u.cons.cookie)
- HarvestConsole(doc, (MPConsoleSocket *) doc->u.cons.cookie);
- doc->dirty = false;
- }
-
- return 0;
- }
-